import os
from typing import Generator

from assertpy.assertions import assert_that
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import jwt
from pydantic import ValidationError
from sqlalchemy.orm import Session

from app import models, schemas
from app.core import security
from app.core.config import settings
from app.core.exception_code import ExceptionCode
from app.dao.user_dao import userDao
from app.db.session import SessionLocal

reusable_oauth2 = OAuth2PasswordBearer(
    tokenUrl=f"{settings.API_V1_STR}/login/access-token"
)

mockUserAccount = os.getenv("MOCK_ACCOUNT")


def getDb() -> Generator:
    try:
        db = SessionLocal()
        yield db
    finally:
        db.close()


def getCurrentUser(
        db: Session = Depends(getDb), token: str = Depends(reusable_oauth2)
) -> models.User:
    try:
        payload = jwt.decode(
            token, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
        )
        token_data = schemas.TokenPayload(**payload)
    except (jwt.JWTError, ValidationError):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Could not validate credentials",
        )
    user = userDao.selectById(db, token_data.sub)
    assert_that(user).is_none().then_throw(ExceptionCode.USER_SETTING_DOES_NOT_EXIST)
    return user

